Ruby 日記 36日目: ネストとレキシカルスコープ
#Ruby_日記 #2021-10-02
https://rex.libertyfish.co.jp/exam_histories/42141/user_answers/8c2200b1-8a6c-4a4d-a680-4fee3018761a
次のプログラムを実行するとどうなりますか
code:gold/ex36/main.rb
module K
CONST = "Good, night"
class P
end
end
module K::P::M
class C
CONST = "Good, evening"
end
end
module M
class C
CONST = "Hello, world"
end
end
class K::P
class M::C
p CONST
end
end
選択肢:
例外が発生する
"Good, night"と表示される
"Good, evening"と表示される
"Hello, world"と表示される
解説:
類似問題は
Ruby 日記 1日目: トップレベルのクラスとネストされたクラス
Ruby 日記 7日目: レキシカルスコープ
Ruby 日記 20日目: レキシカルスコープとクラスの継承
Ruby 日記 32日目: 定数の探索順位
あたりかな?
この問題の p CONST で参照しているのは K::P::M::C
このレキシカルスコープ内で定義されているCONSTがあれば探す
code:rb
module K::P::M
class C
CONST = "Good, evening"
end
end
が、まさにそう
2021-12-07追記
過去の自分が書いた解説を見ると「それはそう」って感じだけど、いざ問題を解こうとすると気が動転してミスったりする
なので正解は「"Good, evening"と表示される」だね
code:sh
# ruby gold/ex36/main.rb
"Good, evening"
/icons/hr.icon
なんとなくググったら、同僚のブログを見つけた!Rubyの定数参照について頭を整理した - takapiのブログ
code:rb
module M
CONST = "Hello"
end
module M
class C
def say
CONST
end
end
end
puts M::C.new.say #=> Hello
moduleを再オープンしている場合でも、値は保持されているので Hello が表示されます。
以下のように M::C と記述するとクラスMの探索は行われないようです。
2021-12-07追記
てか、M::CのMがrootに定義さえたMモジュールなのか、別で定義されたMクラスなのか、も分からないからかな?
module M と class Mって同時に定義できなそうではあるけど
code:rb
module M
CONST = "Hello"
end
class M::C
def say
CONST
end
end
puts M::C.new.say #=> uninitialized constant M::C::CONST (NameError)
このへん引っかかりやすいよね〜〜
Ruby 日記 7日目: レキシカルスコープ#612f6cfa4492e80000014025 に書いたのと同じ話だ